package com.ezlcp.commons.excel;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.metadata.style.WriteFont;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.ezlcp.commons.constant.Constants;
import com.ezlcp.commons.tool.StringUtils;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.springframework.http.HttpHeaders;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author Elwin ZHANG
 * @description: <br/>
 * @date 2022/7/25 13:42
 */
public class EasyExcelUtil {

    //获取多表头
    public static List<List<String>> constructMutiExportFieldColumns(String title, String columns, String field) {
        JSONArray colArr = JSONArray.parseArray(columns);
        List<List<String>> list = new ArrayList<>();
        for (int i = 0; i < colArr.size(); i++) {
            JSONObject obj = colArr.getJSONObject(i);
            String name = obj.getString(field);
            String childColumns = obj.getString("children");
            List<String> fieldsList = new ArrayList<>();
            fieldsList.add(title);
            fieldsList.add(name);
            if (StringUtils.isNotEmpty(childColumns) && !"[]".equals(childColumns)) {
                list.addAll(constructMutiExport(childColumns, fieldsList, field));
            } else {
                list.add(fieldsList);
            }
        }
        return list;
    }

    private static List<List<String>> constructMutiExport(String columns, List<String> fields, String field) {
        JSONArray colArr = JSONArray.parseArray(columns);
        List<List<String>> tmpFeidls = new ArrayList<>();
        for (int i = 0; i < colArr.size(); i++) {
            List<String> tmpField = new ArrayList<>();
            tmpField.addAll(fields);
            JSONObject obj = colArr.getJSONObject(i);
            String name = obj.getString(field);
            String childColumns = obj.getString("children");
            tmpField.add(name);
            if (StringUtils.isNotEmpty(childColumns) && !"[]".equals(childColumns)) {
                tmpFeidls.addAll(constructMutiExport(childColumns, tmpField, field));
            } else {
                tmpFeidls.add(tmpField);
            }
        }
        return tmpFeidls;
    }

    //获取单表头
    public static List<List<String>> constructSingleExportFieldColumns(String title, String columns, List<List<String>> head, String field) {
        JSONArray colArr = JSONArray.parseArray(columns);
        for (int i = 0; i < colArr.size(); i++) {
            JSONObject obj = colArr.getJSONObject(i);
            String name = obj.getString(field);
            String childColumns = obj.getString("children");
            if (StringUtils.isNotEmpty(childColumns) && !"[]".equals(childColumns)) {
                constructSingleExportFieldColumns(title, childColumns, head, field);
            } else {
                List<String> fieldsList = new ArrayList<>();
                fieldsList.add(title);
                fieldsList.add(name);
                head.add(fieldsList);
            }
        }
        return head;
    }

    public static void writeExcel(String fileName, List<List<String>> head, List<List<Object>> data, HttpServletResponse response) {
        try {
            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding("utf-8");
            fileName = URLEncoder.encode(fileName, "UTF-8");
            response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
            EasyExcel.write(response.getOutputStream()).head(head).sheet("模板").doWrite(data);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 读取EXCEL数据。
     *
     * @param multipartFile 文件
     * @param beginRow      开始行
     * @param sheetNo       第几个表格
     * @return
     * @throws IOException
     */
    public static List<Map<Integer, String>> readExcel(MultipartFile multipartFile, String beginRow, Integer sheetNo) throws IOException {
        com.ezlcp.commons.excel.ExcelDataListener listener = new com.ezlcp.commons.excel.ExcelDataListener();
        EasyExcel.read(multipartFile.getInputStream(), listener).sheet(sheetNo).doRead();
        if (!"".equals(beginRow)) {
            listener.setBeginRow(Integer.parseInt(beginRow));
        }
        return listener.getList();
    }

    /***
     * @description: EXCEL导出
     * @param response Http Servlet 响应
     * @param fileName 文件名称
     * @param data 导出内容
     * @param head EXCEL表头
     * @author Weixuan LONG
     * @date 2022/10/21 15:32
     */
    public static <T> void export(HttpServletResponse response, String fileName,
                           List<T> data, List<List<String>> head) {
        try {
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setCharacterEncoding("utf-8");
            // 这里URLEncoder.encode可以防止中文乱码
            String encodedFileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8.name()).replaceAll("\\+", "%20");
            response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename*=utf-8''" + encodedFileName + ".xlsx");
            // 这里需要设置不关闭流
            EasyExcel.write(response.getOutputStream())
                    .head(head)
                    .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
                    .sheet("Sheet1")
                    // 设置单元格宽度自适应
                    .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
                    // 设置单元格高度和字体
                    .registerWriteHandler(getHeightAndFontStrategy())
                    .doWrite(data);
        } catch (Exception e) {
            // 重置response
            throw new RuntimeException("下载文件失败", e);
        }
    }

    /***
     * @description: 自定义Excel导出策略，设置表头和数据行的字体和高度
     * @return com.alibaba.excel.write.style.HorizontalCellStyleStrategy
     * @author Weixuan LONG
     * @date 2022/10/21 15:33
     */
    private static HorizontalCellStyleStrategy getHeightAndFontStrategy() {
        WriteCellStyle headWriteCellStyle = new WriteCellStyle();
        WriteFont headWriteFont = new WriteFont();
        headWriteFont.setFontHeightInPoints(Constants.SHORT1);
        headWriteFont.setBold(true);
        headWriteCellStyle.setWriteFont(headWriteFont);
        WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
        WriteFont contentWriteFont = new WriteFont();
        contentWriteFont.setFontHeightInPoints(Constants.SHORT1);
        contentWriteCellStyle.setWriteFont(contentWriteFont);
        contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
        return new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);
    }
}